// solution copytight Christan Grant
#include <stdio.h>

#define INF 999
#define mynode (int)3 
#define TABLE_LENGTH 4

extern struct rtpkt {
  int sourceid;       /* id of sending router sending this pkt */
  int destid;         /* id of router to which pkt being sent 
                         (must be an immediate neighbor) */
  int mincost[TABLE_LENGTH];    /* min cost to node 0 ... 3 */
  };

extern int TRACE;
extern int YES;
extern int NO;

int connectcosts3[TABLE_LENGTH];

struct distance_table 
{
  int costs[TABLE_LENGTH][TABLE_LENGTH];
} dt3;

void printdt3(struct distance_table *dtptr);
void linkhandler3(int linkid, int newcost);
extern void printFull(int dtptr[][TABLE_LENGTH]);
int costto3(int node);
extern void printdt(struct distance_table *dtptr, char* file_name);
extern char* table_filename;

/* students to write the following two routines, and maybe some others */


int rtinit3() 
{
   FILE *fp = NULL;
   int val0,val1,val2,val3;
   int i=0;

   fp = fopen(table_filename,"r");
      
   if (fp == NULL){
      printf("Error opening file\n");
      return 1; 
   }
   
   for(i=0;i < TABLE_LENGTH; ++i){
      fscanf(fp, "%d %d %d %d",&val0, &val1, &val2, &val3);
      dt3.costs[i][0] = val0;
      dt3.costs[i][1] = val1;
      dt3.costs[i][2] = val2;
      dt3.costs[i][3] = val3;
      if(i == mynode){
         connectcosts3[0] = val0;
         connectcosts3[1] = val1;
         connectcosts3[2] = val2;
         connectcosts3[3] = val3;
      }
   } 
   
   fclose( fp );
   
   struct rtpkt pkt2send;
   /* send routs to direct neighbors */
   for(i=0;i < TABLE_LENGTH; ++i){
      if((connectcosts3[i] != INF)&&(mynode != i)){
         pkt2send.sourceid = mynode;
         pkt2send.destid = i;
         memcpy(pkt2send.mincost, dt3.costs[mynode], sizeof(pkt2send.mincost)); 
         tolayer2(pkt2send);
      }
   }
   //printf("ID: %d\n", mynode);
   //printFull(dt3.costs);   
   return 0;
}


void rtupdate3(rcvdpkt)
  struct rtpkt *rcvdpkt;
  
{
   int i=0;
   int source = rcvdpkt->sourceid;
   int dest = rcvdpkt->destid;
    /* Update all other rows in this matrix bc it is from the node*/
   for(i=0; i < TABLE_LENGTH; ++i){
      if(dt3.costs[source][i] > rcvdpkt->mincost[i]){
         dt3.costs[source][i] = rcvdpkt->mincost[i];
      }
   }

   for(i=0; i < TABLE_LENGTH; ++i){
      if(dt3.costs[i][source] > rcvdpkt->mincost[i]){
         dt3.costs[i][source] = rcvdpkt->mincost[i];
      }
   }


   
   for(i=0; i < TABLE_LENGTH; ++i){
      int mincost = rcvdpkt->mincost[i];
      if(i == source){
      /* if this packet equals itself */
         continue;
      }
      /* check to see if this is less than original */
      else if( costto3(i) > (costto3(source) + mincost)){
         linkhandler3(i, costto3(source)+ mincost);
         int j = i;
         struct rtpkt pkt2send;
         /* send routs to direct neighbors */
         for(i=0;i < TABLE_LENGTH; ++i){
            if((connectcosts3[i] != INF)&&(mynode != i)){
               pkt2send.sourceid = mynode;
               pkt2send.destid = i;
               memcpy(pkt2send.mincost, dt3.costs[mynode], sizeof(pkt2send.mincost)); 
               tolayer2(pkt2send);
            }
         }
         i = j;
      }
   }
   if(TRACE >= 2){
      printFull(dt3.costs);
   }
}


void printdt3(dtptr)
  struct distance_table *dtptr;
  
{
  printf("             via     \n");
  printf("   D3 |    0     2 \n");
  printf("  ----|-----------\n");
  printf("     0|  %3d   %3d\n",dtptr->costs[0][0], dtptr->costs[0][2]);
  printf("dest 1|  %3d   %3d\n",dtptr->costs[1][0], dtptr->costs[1][2]);
  printf("     2|  %3d   %3d\n",dtptr->costs[2][0], dtptr->costs[2][2]);

}


void linkhandler3(linkid, newcost)   
int linkid, newcost;   
/* called when cost from 3 to linkid changes from current value to newcost*/
/* You can leave this routine empty if you're an undergrad. If you want */
/* to use this routine, you'll need to change the value of the LINKCHANGE */
/* constant definition in prog3.c from 0 to 1 */

{
   dt3.costs[mynode][linkid] = newcost;
   //printf("\n3--[%d][%d][%d]\n",mynode,linkid,newcost);
}

int costto3(int _node){
   return dt3.costs[mynode][_node];
}
